package server

import (
	"sync"
	"ws-demo-go/internal/message/common"
	"ws-demo-go/internal/transport/server"
	"ws-demo-go/pkg/logger"
)

type Server struct {
	transServer *server.Server         // 传输层服务端
	connections map[string]*Connection // 管理所有消息层连接
	mu          sync.RWMutex           // 保护 connections 并发安全
	hook        Hook                   // 消息层服务端启动时生命周期的一些钩子函数
}

// NewMessageServer 创建消息层服务端实例
func NewMessageServer(addr string) *Server {
	ms := &Server{
		transServer: server.NewTransportServer(addr),
		connections: make(map[string]*Connection),
	}
	ms.transServer.SetHook(ms)

	return ms
}

// Start 启动消息层服务端
func (ms *Server) Start() error {
	return ms.transServer.Start()
}

// Stop 停止消息层服务端
func (ms *Server) Stop() {
	ms.transServer.Stop()
}

// GetConnection 获取指定ID的连接
func (ms *Server) GetConnection(connID string) *Connection {
	ms.mu.RLock()
	defer ms.mu.RUnlock()
	return ms.connections[connID]
}

func (ms *Server) OnConnected(transConn *server.Connection) {
	// 创建消息层连接
	conn := NewConnection(transConn)
	connID := transConn.GetConnID()

	// 保存连接
	ms.mu.Lock()
	ms.connections[connID] = conn
	ms.mu.Unlock()

	// 调用业务层 OnConnected 回调
	if onConnected := ms.hook.OnConnected; onConnected != nil {
		onConnected(conn)
	}
}

func (ms *Server) OnDisconnected(connID string) {
	// 查找连接
	ms.mu.Lock()
	conn, exists := ms.connections[connID]
	if exists {
		delete(ms.connections, connID)
	}
	ms.mu.Unlock()

	// 调用业务层回调
	if exists {
		onDisconnect := ms.hook.OnDisconnected
		if onDisconnect != nil {
			onDisconnect(conn)
		}
	}
}

func (ms *Server) OnMessage(connID string, data []byte) {
	// 解码二进制数据为Message对象
	msg := &common.Message{}
	err := common.Decode(data, msg)
	if err != nil {
		logger.Error("Decode message failed: %v", err)
		return
	}

	// 查找连接
	ms.mu.RLock()
	conn, exists := ms.connections[connID]
	ms.mu.RUnlock()

	if !exists {
		logger.Error("Connection not found for message: %s", connID)
		return
	}

	// 调用业务层回调
	onMessage := ms.hook.OnMessage
	if onMessage != nil {
		onMessage(conn, msg)
	}
}

// SetHook 设置回调钩子
func (ms *Server) SetHook(hook Hook) {
	ms.hook = hook
}
